package com.hengpeng.msls.port.client;

import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.hengpeng.common.configuration.ConfigProviderFactory;
import com.hengpeng.common.constant.Constant;
import com.hengpeng.common.util.MD5;
import com.hengpeng.common.util.ObjectHelper;
import com.hengpeng.msls.controller.BaseController;
import com.hengpeng.msls.port.client.message.MessagePackage;
import com.hengpeng.msls.port.client.message.PrivateMessage;
import com.hengpeng.msls.port.client.message.TransMessage;
import com.hengpeng.msls.port.client.vo.ResponseCode;
import com.hengpeng.msls.port.client.vo.client.WapTransType;
import com.hengpeng.msls.service.client.ClientRequestFacade;
import com.hengpeng.msls.util.CommUtil;

/**
 * <pre>
 * HTTP远程服务控制器
 * </pre>
 * @author linriqing
 * @version 1.0, 2012-3-8
 */
@Controller("HttpClientRequestController")
@RequestMapping(value = "/clientrequest")
public class HttpClientRequestController extends BaseController
{
	private static final String CLIENT_REQUEST_DATETIME_PATTERN = "yyyyMMddHHmmss";

	private static final Map<String, String> clientKeyMap = new HashMap<String, String>();

	private static final GsonBuilder gsonBuilder = createGson();

	private final static Log logger = LogFactory.getLog(HttpClientRequestController.class);

	private static String serverPublicKey = ConfigProviderFactory.getInstance(Constant.HP_COMMON_PROPERTIES_FILEPATH)
			.getConfigByPrimaryKey("wapserver.publickey");

	public static GsonBuilder createGson()
	{
		GsonBuilder gsonBuilder = new GsonBuilder();
		gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>()
		{
			@Override
			public Date deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
					throws JsonParseException
			{
				try
				{
					SimpleDateFormat sdf = new SimpleDateFormat(CLIENT_REQUEST_DATETIME_PATTERN);
					return sdf.parse(json.getAsString());
				}
				catch (ParseException e)
				{
					throw new RuntimeException("日期{" + json.getAsString() + "}格式不对,Pattern应该为:"
							+ CLIENT_REQUEST_DATETIME_PATTERN, e);
				}
				catch (Exception e)
				{
					throw new RuntimeException("日期转换错误{" + json.toString() + "}", e);
				}
			}
		});
		gsonBuilder.registerTypeAdapter(Date.class, new JsonSerializer<Date>()
		{
			@Override
			public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2)
			{
				SimpleDateFormat sdf = new SimpleDateFormat(CLIENT_REQUEST_DATETIME_PATTERN);
				return new JsonPrimitive(sdf.format(arg0));
			}
		});
		return gsonBuilder;
	}

	private static String formatDate(String pattern, Date date)
	{
		return new SimpleDateFormat(pattern, Locale.getDefault()).format(date);
	}

	@Autowired
	private ClientRequestFacade clientRequestFacade;

	@RequestMapping(value = "/exchangeKey", method = RequestMethod.POST)
	@ResponseBody
	public String exchangeKey(@RequestParam String clientPublicKey, @RequestParam String clientId)
	{
		clientKeyMap.put(clientId, clientPublicKey);
		return serverPublicKey;
	}

	@RequestMapping(value = "/process", method = RequestMethod.POST)
	@ResponseBody
	public MessagePackage process(HttpServletRequest request, @RequestBody MessagePackage jsonMessage)
	{
		try
		{
			String clientId = jsonMessage.getClientId();
			String secretKey = ConfigProviderFactory.getInstance(Constant.HP_COMMON_PROPERTIES_FILEPATH)
					.getConfigByPrimaryKey("access.password." + clientId);
			if (secretKey == null)
			{
				jsonMessage.setResponseCode(ResponseCode.WRONG_PARTNER.getCode());
				jsonMessage.setResponseMessage(ResponseCode.WRONG_PARTNER.getMessage());
				return jsonMessage;
			}
			else
			{
				secretKey = (secretKey == null ? "" : secretKey);
				String validDigestSrc = clientId + "#" + secretKey + "#" + jsonMessage.getMessageId() + "#"
						+ jsonMessage.getTransTime() + "#" + jsonMessage.getMessage();
				String digest = MD5.encodeString(validDigestSrc, "UTF-8");
				WapTransType transType = jsonMessage.getTransType();
				if (!digest.equals(jsonMessage.getDigest()))
				{
					logger.info("digest invalidate, src： " + validDigestSrc + ", actul: " + jsonMessage.getDigest()
							+ ", expect:" + digest);
					MessagePackage mp = new MessagePackage(clientId, jsonMessage.getMessageId(), transType,
							jsonMessage.getTransTime(), jsonMessage.getDigest(), jsonMessage.getMessage());
					mp.setResponseCode(ResponseCode.WRONG_DIGEST.getCode());
					mp.setResponseMessage(ResponseCode.WRONG_DIGEST.getMessage());
					return mp;
				}
				else
				{
					Gson create = gsonBuilder.create();
					logger.info("TransType[" + transType.name() + "] request: " + ObjectHelper.toJson(jsonMessage));
					TransMessage fromJson = null;
					if (StringUtils.hasText(jsonMessage.getMessage()))
					{
						Class<?> requestType = transType.getRequestType();
						if (PrivateMessage.class.isAssignableFrom(requestType))
						{
							fromJson = (PrivateMessage) create.fromJson(jsonMessage.getMessage(), requestType);
							((PrivateMessage) fromJson).setClientIP(CommUtil.getIp(request));
						}
						else
						{
							fromJson = (TransMessage) create.fromJson(jsonMessage.getMessage(), requestType);
						}
						// 根据域名识别访问的会员店
						fromJson.setDomain(CommUtil.getBasePath(request));
//						fromJson.setStoreId(getStoreId(request));
						fromJson.setClientId(clientId);
					}

					Object process = clientRequestFacade.process(fromJson, transType, transType.getResponseType());
					String json = create.toJson(process);
					logger.info("TransType[" + transType.name() + "] response: " + json);

					String date = formatDate(CLIENT_REQUEST_DATETIME_PATTERN, new Date());
					String messageId = jsonMessage.getMessageId();
					String md5Hex = MD5.encodeString(clientId + "#" + secretKey + "#" + messageId + "#" + date + "#"
							+ json, "UTF-8");
					return new MessagePackage(clientId, messageId, transType, date, md5Hex, json);
				}
			}
		}
		catch (Exception e)
		{
			logger.error("服务器响应错误。", e);
			jsonMessage.setResponseCode(ResponseCode.UNKOWN_ERROR.getCode());
			jsonMessage.setResponseMessage(ResponseCode.UNKOWN_ERROR.getMessage());
			return jsonMessage;
		}
	}
}
